# queue.rb
# Copyright (C) 2006 Akira TAGOH

# Authors:
#   Akira TAGOH  <at@gclab.org>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

require 'thread'


Thread.abort_on_exception = true if $DEBUG

module PRUNE

=begin rdoc

== PRUNE::Queue

=end

  class Queue

=begin rdoc

=== PRUNE::Queue#new

=end

    def initialize
      @queue = []
      @lockkey = Mutex.new
    end # def initialize

=begin rdoc

=== PRUNE::Queue#empty?

=end

    def empty?
      return _transaction(:EMPTY)
    end # empty?

=begin rdoc

=== PRUNE::Queue#push(*args)

=end

    def push(*args)
      return _transaction(:PUSH, *args)
    end # def push

=begin rdoc

=== PRUNE::Queue#shift

=end

    def shift
      retval = _transaction(:SHIFT)
      if retval.kind_of?(Array) && retval.length == 1 then
        retval = retval[0]
      end

      return retval
    end # def shift

=begin rdoc

=== PRUNE::Queue#unshift(arg)

=end

    def unshift(arg)
      return _transaction(:UNSHIFT, arg)
    end # def unshift

=begin rdoc

=== PRUNE::Queue#clear

=end

    def clear
      return _transaction(:CLEAR)
    end # def clear

=begin rdoc

=== PRUNE::Queue#size

=end

    def size
      return _transaction(:SIZE)
    end

    alias length size

=begin rdoc

=== PRUNE::Queue#each(&block)

=end

    def each(&block) # :yields: object
      return _transaction(:EACH, &block)
    end # def each

=begin rdoc

=== PRUNE::Queue#include?(arg)

=end

    def include?(arg)
      return _transaction(:INCLUDE, arg)
    end # def include?

=begin rdoc

=== PRUNE::Queue#delete(arg)

=end

    def delete(arg)
      return _transaction(:DELETE, arg)
    end # def delete

=begin rdoc

=== PRUNE::Queue#delete_if(&block)

=end

    def delete_if(&block) # :yields: objects
      return _transaction(:DELETE_IF, &block)
    end # def delete_if

=begin rdoc

=== PRUNE::Queue#[](arg)

=end

    def [](arg)
      return _transaction(:ARRAY, arg)
    end # def []

    private

    def _transaction(mode, *args, &block)
      retval = nil

      @lockkey.synchronize do
        case mode
        when :EMPTY
          retval = @queue.empty?
        when :PUSH
          if args.length == 1 then
            retval = @queue.push(args[0])
          else
            retval = @queue.push(args)
          end
        when :SHIFT
          *retval = @queue.shift
        when :UNSHIFT
          retval = @queue.unshift(args[0])
        when :CLEAR
          @queue.clear
        when :SIZE
          retval = @queue.length
        when :EACH
          retval = @queue.each(&block)
        when :INCLUDE
          retval = @queue.include?(args[0])
        when :DELETE
          retval = @queue.delete(args[0])
        when :DELETE_IF
          retval = @queue.delete_if(&block)
        when :ARRAY
          retval = @queue[args[0]]
        else
          PRUNE.Fail(PRUNE::Error::UnknownQueueFunction, mode)
        end
      end

      return retval
    end # def _transaction

  end # class Queue

end # module PRUNE
